package data.utils;

import java.util.ArrayList;

import controls.edit.ParamControl;
import controls.visu.BandControl;

import data.visu.enums.E_BandTypes;
import data.visu.enums.E_DisplayDataTypes;
import data.visu.structures.Range;
import data.visu.structures.RangeAndValue;
import data.visu.structures.ValueAndString;

/**
 * @author Charles Perin
 * 29 mars 2011
 * LIMSI - INRIA Rennes
 * charles.perin@free.fr
 *
 */
public class Interpolators {

	public static void bezierInterpolation(ParamControl paramControl, int nbPts, int x1, Object o1, int x2, Object o2, int curvatureUp, int curvatureDown){

		int ampX = x2-x1;

		if(paramControl.getDisplayDataControl().getType().equals(E_DisplayDataTypes.CURVE)){
			int y1 = (Integer)o1;
			int y2 = (Integer)o2;
			int ampY = Math.abs(y1-y2)+1;

			int nbInterPts = Math.min(ampX, ampY);

			// Coordonnees des points de controles
			float[] xValues;
			float[] yValues;
			xValues=new float[nbPts];
			yValues=new float[nbPts];

			xValues[0]=x1;
			yValues[0]=y1;

			//si monte
			if(y2>=y1){
				xValues[1]=(float) (x2-ampX*(curvatureDown/100.0));
				yValues[1]=(float) (y1+ampY*(curvatureDown/100.0));
				xValues[2]=(float) (x1+(ampX*(curvatureUp/100.0)));
				yValues[2]=(float)(y2-ampY*(curvatureUp/100.0));
			}
			//si descend
			else{
				xValues[1]=(float) (x1+ampX*(curvatureUp/100.0));
				yValues[1]=(float) (y1-(ampY-ampY*(curvatureUp/100.0)));
				xValues[2]=(float) (x2-ampX*(curvatureDown/100.0));
				yValues[2]=(float)(y2+(ampY-ampY*(curvatureDown/100.0)));
			}


			xValues[3]=x2;
			yValues[3]=y2;

			Bezier bez = new Bezier(nbPts,xValues,yValues );

			ArrayList<RangeAndValue>list = new ArrayList<RangeAndValue>();
			float previousX2=-1;
			float previousY=-1;
			int currentX1=-1;
			int currentX2=-1;
			float currentY=-1;
			for(int i=0;i<nbInterPts;i++){
				float dt=(float)1/nbInterPts;
				float t=(float)i/nbInterPts;
				currentX1 = (int) bez.xBezier(t);
				currentX2 = (int) bez.xBezier(t+dt);
				currentY = bez.yBezier(t+dt);
				if(i==0){
					list.add(new RangeAndValue(new Range(currentX1, currentX2, paramControl.getDisplayDataControl()), new Double(currentY)));	
					previousX2=currentX2;
					previousY=currentY;
				}
				else{
					if(previousX2!=currentX2 && previousY != currentY){
						list.add(new RangeAndValue(new Range(currentX1, currentX2, paramControl.getDisplayDataControl()), new Double(currentY)));	
						previousX2=currentX2;
						previousY=currentY;
					}
					else{
						//si n'avance pas en X
						if(previousX2==currentX2){
							list.get(list.size()-1).setValue(new Double(currentY));
							previousY=currentY;
						}
						//si n'avance pas en Y
						else if(previousY==currentY){
							list.get(list.size()-1).getRange().setMax(currentX2);
							previousX2=currentX2;
						}
					}
				}
			}
			if(list.size()>0){
				for(RangeAndValue rv:list){
					paramControl.getDisplayDataControl().getDataSet().addRange2Map(rv.getRange(), rv.getValue());
				}
			}
		}

		else if(paramControl.getDisplayDataControl().getType().equals(E_DisplayDataTypes.BAND)){
			int y1 = (Integer)o1;
			int y2 = (Integer)o2;

			int ampY = Math.abs(y2-y1)+1;

			int nbInterPts = Math.min(ampX, ampY);

			// Coordonnees des points de controles
			float[] xValues;
			float[] yValues;
			xValues=new float[nbPts];
			yValues=new float[nbPts];

			boolean goUp = (y2>=y1);

			xValues[0]=x1;
			yValues[0]=y1;

			//si monte
			if(goUp){
				xValues[1]=(float) (x2-ampX*(curvatureDown/100.0));
				yValues[1]=(float) (y1+ampY*(curvatureDown/100.0));
				xValues[2]=(float) (x1+(ampX*(curvatureUp/100.0)));
				yValues[2]=(float)(y2-ampY*(curvatureUp/100.0));
			}
			//si descend
			else{
				xValues[1]=(float) (x1+ampX*(curvatureUp/100.0));
				yValues[1]=(float) (y1-(ampY-ampY*(curvatureUp/100.0)));
				xValues[2]=(float) (x2-ampX*(curvatureDown/100.0));
				yValues[2]=(float) (y2+(ampY-ampY*(curvatureDown/100.0)));
			}
			xValues[3]=x2;
			yValues[3]=y2;

			Bezier bez = new Bezier(nbPts,xValues,yValues );

			E_BandTypes type = ((BandControl)paramControl.getDisplayDataControl()).getBandType();
			ValueAndString[] tab = type.getValues();
			ArrayList<RangeAndValue>list = new ArrayList<RangeAndValue>();
			int y = y1;
			for(int i=0;i<nbInterPts;i++){
				float dt=(float)1/nbInterPts;
				float t=(float)i/nbInterPts;
				System.out.println("y="+y);
					list.add(new RangeAndValue(new Range((int) bez.xBezier(t), (int) bez.xBezier(t+dt), paramControl.getDisplayDataControl()), tab[y]));	
					if(goUp)y++;
					else y--;
			}
			if(list.size()>0){
				for(RangeAndValue rv:list){
					paramControl.getDisplayDataControl().getDataSet().addRange2Map(rv.getRange(), rv.getValue());
				}
			}
		}
		else System.err.println("Interpolators: Bezier: nu Curve ni Band");
	}
}
